﻿@using System.Web
@using System.Linq
@using System.Collections.Generic
@using MvcMiniProfiler
@model MvcMiniProfiler.UI.MiniProfilerResultsModel
@{
    var p = Model.MiniProfiler;
    var parentLookup = new Dictionary<SqlTiming, Timing>();
    var sqlCounts = new Dictionary<string, int>();

    var hasSqlTimings = p.HasSqlTimings;
    var showTrivialToggle = false;
    var allTimingsTrivial = true;
}
@functions 
{
    // IMPORTANT: RazorEngine does not encode @object.ToString() calls by default!
    string e(object o)
    {
        return o == null ? "" : HttpUtility.HtmlEncode(o);
    }
    // to help with display, put some space around sammiched commas
    string AddSpacesToParameters(string commandString) 
    {
        return e(System.Text.RegularExpressions.Regex.Replace(commandString, @"[^\s],[^\s]", ", "));
    }
}
@helper RenderNumber(double ms, string unit = "", string format = "0.0") 
{
    <span class="number">
        @ms.ToString(format)
        @if (!string.IsNullOrWhiteSpace(unit)) 
        {
            <span class="unit">@unit</span>
        }
    </span>
}
@if (!Model.IsPopup)
{
<text> 
<html>
<head>
    <title>@p.Name (@p.DurationMilliseconds ms) - MiniProfiler Results</title>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
    <link type="text/css" rel="stylesheet/less" href="/mini-profiler-includes.less?v=@MiniProfiler.Settings.Version" />
    <script type="text/javascript" src="/mini-profiler-includes.js?v=@MiniProfiler.Settings.Version"></script>
    <script type="text/javascript">
        jQuery(function() { MiniProfiler.init(); });
    </script>
</head>
<body>
</text>
}
<div class="profiler-result @(Model.IsPopup ? "" : "profiler-result-full")">
    <div class="profiler-button">
        @RenderNumber(p.DurationMilliseconds, "ms")
    </div>

    <div class="profiler-popup">
        <div class="info">
            <span class="name">@e(p.Name) <span class="overall-duration">(@p.DurationMilliseconds.ToString("0.0")ms)</span></span>
            <span class="server-time">@e(p.MachineName) at @e(p.Started.ToString("u"))</span>
        </div>
        <div class="profiler-output">
            <table class="timings">
            <thead>
                <tr>
                    <th></th>
                    <th>duration (ms)</th>
                    <th class="duration-with-children">with children (ms)</th>
                    <th class="time-from-start">from start (ms)</th>
                @if (p.HasSqlTimings)
                {
                    <th colspan="2">query time (ms)</th>
                }
                </tr>
            </thead>
            <tbody>
            @foreach (var t in p.GetTimingHierarchy())
            {
                bool flagDuplicates = false;
                if (t.IsTrivial)
                {
                    if (!showTrivialToggle)
                    {
                        showTrivialToggle = true;
                    }
                }
                else 
                {
                    allTimingsTrivial = false; 
                }
                <tr class="@(t.IsTrivial ? "trivial" : "")" data-timing-id="@t.Id">
                    <td class="label">
                        <span class="indent">@for (int i = 0; i < t.Depth; i++) { <text>&nbsp;</text> }</span>
                        @e(t.Name)
                    </td>
                    <td class="duration" title="duration of this step without any children's durations">
                        @RenderNumber(t.DurationWithoutChildrenMilliseconds)
                    </td>
                    <td class="duration duration-with-children" title="duration of this step and its children">
                        @RenderNumber(t.DurationMilliseconds.GetValueOrDefault())
                    </td>
                    <td class="duration time-from-start" title="time ellapsed since profiling started">
                        <span class="unit">+</span>@RenderNumber(t.StartMilliseconds)
                    </td>
                @if (t.HasSqlTimings)
                {
                    t.SqlTimings.ForEach(s => {
                        parentLookup[s] = t;
                        int count;
                        if (!sqlCounts.TryGetValue(s.CommandString, out count)) { sqlCounts.Add(s.CommandString, 1); }
                        else { flagDuplicates = true; sqlCounts[s.CommandString] = count + 1; }                        
                    }); // we'll look this up later when rendering the queries
                    var readers = t.SqlTimings.Count(s => s.ExecuteType == ExecuteType.Reader);
                    var scalers = t.SqlTimings.Count(s => s.ExecuteType == ExecuteType.Scalar);
                    var nons = t.SqlTimings.Count(s => s.ExecuteType == ExecuteType.NonQuery);
                    var css = flagDuplicates ? " warning" : "";
                    var title = flagDuplicates ? "duplicate queries detected -" : "";
                    <td class="duration@(css)" title="@title @readers reader, @scalers scaler, @nons non-query statements executed">
                        <a class="queries-show">
                        @if (flagDuplicates) 
                        {
                            <span class="nuclear">!</span> 
                        }
                            @RenderNumber(t.SqlTimings.Count, "sql", "0")
                        </a>
                    </td>
                    <td class="duration" title="aggregate duration of all queries in this step (excludes children)">
                        @RenderNumber(t.SqlTimings.Sum(s => s.DurationMilliseconds))
                    </td>
                }
                else if (hasSqlTimings) 
                {
                    <td colspan="2"></td>
                }
                </tr>
            }
            </tbody>
            <tfoot>
                <tr>
                    <td colspan="3">
                        <a href="/mini-profiler-results?id=@p.Id" target="_blank">share</a>
                    @if (showTrivialToggle)
                    { 
                        <a class="toggle-trivial"
                           data-show-on-load="@(allTimingsTrivial ? "true" : "")"
                           title="toggles any rows with &lt; @MiniProfiler.Settings.TrivialDurationThresholdMilliseconds ms">show trivial</a>
                    }
                        <a class="toggle-duration-with-children" title="toggles column with aggregate child durations">show time with children</a>
                    </td>                  
                @if (p.HasSqlTimings)
                {
                    <td colspan="2" class="percent-in-sql" title="percentage of total time spent executing sql">
                        @RenderNumber(p.DurationMillisecondsInSql / p.DurationMilliseconds * 100, "% in sql")
                    </td>
                }
                </tr>
            </tfoot>
            </table>
        </div>
    </div>
@{ List<SqlTiming> sqlTimings; }
@if ((sqlTimings = p.GetSqlTimings()).Any())
{
    <div class="profiler-queries">
        <table>
        <thead>
            <tr>
                <th style="text-align:right">step<br />time from start<br />query type<br />duration</th>
                <th style="text-align:left">call stack<br />query</th>
            </tr>
        </thead>
        <tbody>
        @{ int i = 0, count; Timing parent = null;}
        @foreach (var s in sqlTimings)
        {
            parent = parentLookup[s];
            <tr class="@(i++ % 2 == 0 ? "" : "odd")" data-timing-id="@parent.Id">
                <td class="info">
                    <div>@parent.Name</div>
                    <div><span class="unit">T+</span>@RenderNumber(s.StartMilliseconds, "ms")</div>
                    <div>@if (sqlCounts.TryGetValue(s.CommandString, out count) && count > 1){
                             <span class="warning">DUPLICATE</span>
                         }@e(s.ExecuteType)</div>
                    <div>@RenderNumber(s.DurationMilliseconds, "ms")</div>
                </td>
                <td>
                    <div class="query">
                        <pre class="stack-trace">@e(s.StackTraceSnippet)</pre>
                        <pre class="prettyprint lang-sql"><code>@AddSpacesToParameters(s.CommandString)</code></pre>
                    </div>
                </td>
            </tr>
        }
        </tbody>
        </table>
    </div>
}
</div>

@if (!Model.IsPopup)
{
@Html.Raw(@"
</body>
</html>")
}